package com.fjwt.gz.task.realname;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fjwt.gz.core.constants.Constants;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.db.bo.ActivityAwardAndSettingBo;
import com.fjwt.gz.db.entity.FansAuthEntity;
import com.fjwt.gz.db.entity.FansAwardEntity;
import com.fjwt.gz.db.entity.FansEntity;
import com.fjwt.gz.db.vo.FansAwardVO;
import com.fjwt.gz.service.impl.ActivityAwardService;
import com.fjwt.gz.service.impl.AgentInfoService;
import com.fjwt.gz.service.impl.FansAuthService;
import com.fjwt.gz.service.impl.FansAwardService;
import com.fjwt.gz.service.impl.FansService;
import com.fjwt.gz.service.impl.SendAwardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@Slf4j
@Component
public class ACTE017ConfirmB1Task {

    @Autowired
    private FansAwardService fansAwardService;
    @Autowired
    private FansService fansService;
    @Autowired
    private FansAuthService fansAuthService;
    @Autowired
    private AgentInfoService agentInfoService;
    @Autowired
    private SendAwardService sendAwardService;
    @Autowired
    private ActivityAwardService activityAwardService;


    private static final int QUERY_PAGE_SIZE = 100; //每次查询数量

//    @Scheduled(cron = "${cron.ACTE017ConfirmB1Task}")//每天2点执行
    @Transactional
    public void start() {
        log.info("开始进入：根据发起邀约转介激活发放卡券，开始时间:{}", DateUtil.now());

        // 当前时间 减去7天
        Date offsetDate = DateUtil.offsetDay(new Date(), -7);
        int currentPageIndex = 1; //当前页码
        while (true) {
            try {
                // 查询七天内的待激活的ACTE017的B1卡券
                IPage<FansAwardVO> fansAwardEntityIPage = fansAwardService.findB1ActivateAward(new Page(currentPageIndex, QUERY_PAGE_SIZE), offsetDate, Constants.AWARD.COUPON, "ACTE017");
                log.info("查询页数：{}，size:{}，获取拉新用户结果list：{}", currentPageIndex, QUERY_PAGE_SIZE, JSONUtil.toJsonStr(fansAwardEntityIPage));
                if (fansAwardEntityIPage == null || fansAwardEntityIPage.getRecords().isEmpty()) { //本次查询无结果, 不再继续查询;
                    break;
                }
                List<FansAwardVO> records = fansAwardEntityIPage.getRecords();
                Set<Long> fansIds = records.stream().map(FansAwardVO::getFansId).collect(Collectors.toSet());
                Set<Long> beInviterIds = records.stream().map(FansAwardVO::getBeInviterId).collect(Collectors.toSet());
                // 邀请人或被邀请人为空跳过
                if (ObjectUtil.isEmpty(fansIds) || ObjectUtil.isEmpty(beInviterIds)) {
                    continue;
                }
                List<FansEntity> fansEntityList = fansService.listByIds(Stream.of(fansIds, beInviterIds).flatMap(Set::stream).collect(Collectors.toSet()));
                if (ObjectUtil.isEmpty(fansEntityList)) {
                    continue;
                }
                // 查询用户信息
                Map<Long, FansEntity> fansMap = fansEntityList.stream().collect(Collectors.toMap(FansEntity::getFansId, Function.identity()));

                // 查询被邀请人的实名信息
                Map<Long, List<FansAuthEntity>> fansAuthMap = new HashMap<>();
                List<FansAuthEntity> beInviterAuthList = fansAuthService.list(FansAuthEntity.gw().in(FansAuthEntity::getFansId, beInviterIds));
                if (ObjectUtil.isNotEmpty(beInviterAuthList)) {
                    fansAuthMap = beInviterAuthList.stream().collect(Collectors.groupingBy(FansAuthEntity::getFansId));
                }

                // 循环数据
                for (FansAwardVO fansAwardVO : records) {
                    log.info("拉新进行卡券激活此时进行处理的信息的是：{}", JSONUtil.toJsonStr(fansAwardVO));

                    // 首先判断邀约的用户是否在fans表  不存在 即不合规 继续下一个
                    FansEntity fansEntity = fansMap.get(fansAwardVO.getFansId());
                    log.info("拉新定时任务卡券激活会员用户信息：{}", JSONObject.toJSONString(fansEntity));
                    if (null == fansEntity) {
                        continue;
                    }
                    // 当被邀请人有多个人邀请时，找到最后的一个邀请人 激活最后一个邀请人的卡券 （激活卡券  B1卡券激活默认调用 ACTE017）
                    List<FansAwardEntity> fansAwardEntityList = fansAwardService.selectB1CouponAwards(fansAwardVO.getBeInviterId(), null);
                    if (!fansAwardVO.getFansAwardId().equals(fansAwardEntityList.get(0).getFansAwardId())) {
                        continue;
                    }
                    // 获取被邀请人的实名信息
                    List<FansAuthEntity> fansAuthList = fansAuthMap.get(fansAwardVO.getBeInviterId());
                    log.info("fansAuthList信息:{}", JSONUtil.toJsonStr(fansAuthList));
                    if (ObjectUtil.isEmpty(fansAuthList)) {
                        continue;
                    }
                    // 通过实名认证返回的信息（数组）中 首先判断是否在对应机构的下属网点中 来判断是否为新客
                    List<String> allSubAgentNo = agentInfoService.queryAllSubAgentNo(fansAwardVO.getAgentNo());
                    List<FansAuthEntity> fansAuthEntityList = fansAuthList.stream().filter(item -> ObjectUtil.isNotEmpty(item.getCstmNo())
                            && ObjectUtil.isNotEmpty(ObjectUtil.isNotEmpty(item.getAuthRepInfo())
                            && allSubAgentNo.contains(item.getAgentNo()))).collect(Collectors.toList());
                    if (ObjectUtil.isEmpty(fansAuthEntityList)) {
                        continue;
                    }
                    // 解析被邀请人最晚的实名开卡时间
                    String openDt = "";
                    for (FansAuthEntity fansAuthEntity : fansAuthEntityList) {
//                        JSONObject authDataJson = JSONObject.parseObject(fansAuthEntity.getAuthRepInfo()).getJSONObject("data");
                        List<JSONObject> cardInfoList = ObjectUtil.isEmpty(fansAuthEntity.getAuthRepInfo()) ? null : JSON.parseArray(fansAuthEntity.getAuthRepInfo(), JSONObject.class);
                        if (ObjectUtil.isEmpty(cardInfoList)) {
                            continue;
                        }
                        String openDate = cardInfoList.stream().map(json -> json.getString("openDt"))
                                .filter(String::isEmpty).map(dateStr -> dateStr.replace("-", "")).max(String::compareTo).orElse("");
                        if (ObjectUtil.isNotEmpty(openDate)) {
                            openDt = ObjectUtil.isEmpty(openDt) ? openDate
                                    : Collections.max(Arrays.asList(openDate, openDt));
                        }
                    }
                    if (ObjectUtil.isEmpty(openDt)) {
                        continue;
                    }
                    // 对开户时间与卡券创建的时间的大小来判断  开户时间小于参与活动时间
                    String createAt = DateUtil.format(fansAwardVO.getCreatedAt(), DatePattern.PURE_DATE_PATTERN);
                    if (openDt.compareTo(createAt) < 0) {
                        // 失效卡券
                        extracted(fansAwardEntityList, "对方非新客");
                        continue;
                    }

                    ActivityAwardAndSettingBo activityAwardAndSettingBo = activityAwardService.getActivityAndApp(fansAwardVO.getAwardId(), fansAwardVO.getAwardType());
                    // 激活奖品
                    sendAwardService.autoActivateAward(BeanUtil.copyProperties(fansAwardVO, FansAwardEntity.class), activityAwardAndSettingBo, fansAwardVO.getAgentNo());
                    //发送公众号消息
                    sendAwardService.sendActivateCouponMsg(activityAwardAndSettingBo.getActivityId(), fansAwardVO.getFansId(), fansAwardVO.getFansAwardId(), fansAwardVO.getAwardId(), activityAwardAndSettingBo.getActivityName(), activityAwardAndSettingBo.getAwardName());
                    // 失效卡券
                    fansAwardEntityList.remove(0);
                    extracted(fansAwardEntityList, "对方已被他人转介");
                }
                currentPageIndex = currentPageIndex + 1;
            } catch (BizException e) {
                //出现异常，直接退出，避免死循环。
                log.error("error", e.getMessage());
                break;
            } catch (Exception e) {
                //出现异常，直接退出，避免死循环。
                log.error("error", e);
                break;
            }
        }
        log.info("结束任务：根据发起邀约转介激活发放卡券，结束时间:{}", DateUtil.now());
    }

    // 失效卡券
    private void extracted(List<FansAwardEntity> fansAwardEntityList, String failDetail) {
        log.info("需要失效B1券的客户名单：{}", JSONObject.toJSONString(fansAwardEntityList));
        if (ObjectUtil.isEmpty(fansAwardEntityList)) {
            return;
        }
        for (FansAwardEntity fansAwardEntity : fansAwardEntityList) {
            JSONObject failJson = JSONObject.parseObject(fansAwardEntity.getExtraJson());
            failJson.put("failDetail", failDetail);
            fansAwardEntity.setState(Constants.FANS_AWARD_STATE.DISABLED);
            fansAwardEntity.setExtraJson(failJson.toJSONString());
        }
        fansAwardService.updateBatchById(fansAwardEntityList);
    }

    private static JSONArray toYyyyMmDd(JSONArray array) {
        JSONArray jsonArray = new JSONArray();
        for (int i = 0; i < array.size(); i++) {
            JSONObject json = JSONObject.parseObject(array.get(i).toString());
            String date = json.getString("openDt");
            String time = date.replaceAll("-", "");
            json.put("openDt", time);
            jsonArray.add(json);
        }
        return jsonArray;
    }



}
